# This file will act as a bridge between the web interface and the backtesting engine.
# It will contain the logic to configure, run, and get results from a backtest.

import json
from datetime import datetime
import pandas as pd
import baostock as bs
import os

# --- 从新模块中导入组件 ---
from . import db
from .models import Signal

# --- 核心修复：直接从安装好的包中导入 ---
from btstrategy_engine import main as engine_main
from btstrategy_engine import utils as engine_utils
# --- 修复结束 ---

def get_status():
    """
    Returns a static status for now.
    In the future, this could check database connections, etc.
    """
    return {"status": "ok", "service": "webapp"}

def ping_engine():
    """
    Calls the ping function from the backtesting engine to check communication.
    """
    return engine_utils.ping()

def get_config_service():
    """
    通过调用引擎中专门提供的函数，来获取策略配置文件。
    这是最健壮、耦合度最低的方式。
    """
    # 直接调用引擎提供的函数
    config = engine_main.get_config()
    
    # 检查引擎是否返回了错误
    if 'error' in config:
        return config, 500
        
    return config

def run_backtest_service(config):
    """
    This function will be called by the web route to start a backtest.
    
    1. It will receive the configuration from the web form.
    2. It will call the backtesting engine's main function.
    3. It will return the path to the report or the results directly.
    """
    print("Received config, starting backtest...")
    print(config)
    
    # Here we will later import and call the main function from btstrategy-engine
    # from btstrategy-engine import main 
    # results = main.run_backtest(config)

    # For now, return a dummy result
    return {"status": "success", "report_path": "dummy_report.csv"}

def run_signal_generation_service(config, force_recache=False):
    """
    【已修复】调用引擎的核心信号生成模块，并将结果存入数据库。
    """
    try:
        # 1. 调用引擎生成原始信号
        print("--- [WebApp Service] 开始调用引擎生成信号... ---")
        buy_signals = engine_main.generate_signals_for_webapp(config, force_recache=force_recache)
        print(f"--- [WebApp Service] 引擎返回 {sum(len(v) for v in buy_signals.values())} 个信号，准备更新数据库... ---")
        
        # 2. 将信号写入数据库（这是一个独立的事务）
        try:
            # 2.1 清空旧信号
            db.session.query(Signal).delete()
            # 2.2 准备新信号对象
            new_signals = []
            for date, stock_list in buy_signals.items():
                for stock_code in stock_list:
                    signal_obj = Signal(
                        stock_code=stock_code,
                        signal_date=date
                    )
                    new_signals.append(signal_obj)
            
            if new_signals:
                db.session.add_all(new_signals)
            
            # 2.3 提交事务
            db.session.commit()
            print(f"--- [WebApp Service] {len(new_signals)} 个新信号已成功写入数据库。 ---")
        
        except Exception as e:
            # 如果数据库写入失败，则回滚
            db.session.rollback()
            print(f"--- [WebApp Service] 数据库写入失败! 错误: {e} ---")
            import traceback
            traceback.print_exc()
            return {"error": f"数据库操作失败: {e}"}, 500

        # 3. 从数据库查询所有信号并返回给前端
        all_db_signals = Signal.query.order_by(Signal.signal_date.desc(), Signal.stock_code.asc()).all()
        
        # 4. 格式化结果以符合前端需求
        results = []
        for i, signal in enumerate(all_db_signals):
            signal_dict = signal.to_dict()
            signal_dict['序号'] = i + 1
            results.append(signal_dict)
            
        return {"data": results}

    except Exception as e:
        # 这个外部except现在只捕获引擎调用或结果格式化阶段的错误
        print(f"--- [WebApp Service] Error in signal generation process: {e} ---")
        import traceback
        traceback.print_exc()
        return {"error": str(e)}, 500

# 注意：这里不再需要finally块中的bs.logout()，因为引擎函数会自己处理。

def get_signal_details_service(signal_id):
    """
    【保留】根据信号ID获取并运行详细的回测。
    """
    try:
        # 1. 根据ID从数据库查询信号记录
        signal = Signal.query.get(signal_id)
        if not signal:
            return {"error": f"Signal with ID {signal_id} not found."}, 404

        print(f"--- [Service] 找到了信号记录: {signal.stock_code} on {signal.signal_date.strftime('%Y-%m-%d')}")

        # 2. 调用引擎进行单次回测
        config = engine_main.get_config()
        if "error" in config:
            return config, 500
            
        backtest_results = engine_main.run_single_backtest_for_webapp(
            stock_code=signal.stock_code,
            signal_date=signal.signal_date,
            config=config
        )

        # 3. 如果回测成功，更新数据库中的记录
        if "error" not in backtest_results:
            # --- 修复日期转换逻辑 ---
            buy_date_str = backtest_results.get('buy_date')
            sell_date_str = backtest_results.get('sell_date')
            
            signal.buy_date = datetime.strptime(buy_date_str, '%Y-%m-%d').date() if buy_date_str else None
            signal.sell_date = datetime.strptime(sell_date_str, '%Y-%m-%d').date() if sell_date_str else None
            # --- 修复结束 ---
            
            signal.pnl = backtest_results.get('pnl')
            signal.pnl_pct = backtest_results.get('pnl_pct')
            signal.status = 'Tested'
            db.session.commit()
            print(f"--- [Service] 已更新 Signal ID: {signal_id} 的回测结果到数据库。")
        else:
             return {"error": f"Engine failed to run backtest: {backtest_results['error']}"}, 500

        return backtest_results, 200

    except Exception as e:
        db.session.rollback()
        print(f"--- [Service] Error getting signal details: {e} ---")
        import traceback
        traceback.print_exc()
        return {"error": str(e)}, 500 